package club.hicode.daydayup.juc;

import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;
import com.github.sd4324530.jtuple.Tuple2;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.StampedLock;

/**
 * 基于时间戳的锁
 *
 * @author Liu Chunfu
 * @date 2018-06-21 上午11:47
 **/
public class StampedLockTest {

    int sum = 0;

    Map<String, Tuple2<Lock, Condition>> map = new ConcurrentHashMap<>(10);

    @Test
    public void testCreate() {
        for (int i = 0; i < 10; i++) {
            String id = i + "";
            Thread thread = new Thread(() -> {
                ReentrantLock lock = new ReentrantLock();
                Condition condition = lock.newCondition();
                System.out.println(Thread.currentThread().getName() + " 启动。。。");
                try {
                    lock.lock();
                    map.put(id, Tuple2.with(lock, condition));
                    condition.await();

                    System.out.println(Thread.currentThread().getName() + "被激活...");
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                    map.remove(id);
                }

            }, "thread-" + i);
            thread.start();
        }

        ThreadUtil.sleep(3, TimeUnit.SECONDS);
        Tuple2<Lock, Condition> tuple2 = map.get("1");
        Lock first = tuple2.first;
        Condition second = tuple2.second;

        try {
            first.lock();
            second.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            first.unlock();
        }

        ThreadUtil.sleep(10, TimeUnit.HOURS);
    }

    @Test
    public void testMain() {
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        try {
            lock.lock();
            condition.await();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }

    private StampedLock stampedLock = new StampedLock();

    public void write() {
        long stamp = stampedLock.writeLock();
        ThreadUtil.sleep(RandomUtil.randomInt(3), TimeUnit.SECONDS);
        sum++;
        stampedLock.unlock(stamp);
    }

    private void read() {

    }

}
